namespace OpenComposite.EII.Repository
{
	using System;
	using System.Collections.Generic;
	using System.Data;
	using System.Drawing;
	using System.IO;
	using System.Text;
	using System.Windows.Forms;
	using System.Xml;
	using System.Xml.Schema;
	using System.Xml.Serialization;

	using OpenComposite.EII.Forms;

	using OpenComposite.Base;
	using OpenComposite.Base.Collections;
	using OpenComposite.Repository.Properties;

	[RepositoryItem(ItemType.Domain, "domains", "domain_id")]
	public class Domain : RepositoryItemBaseEx
	{
		#region Initialization

		/// <summary>
		/// Initializes a new instance of the <see cref="Domain"/> class.
		/// </summary>
		public Domain()
			: base("domain_id", "domain_nm", "domain_desc", "domain_ntext", Resources.sNewDomain)
		{
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="Domain"/> class.
		/// </summary>
		/// <param name="bCreateNew">if set to <c>true</c> [b create new].</param>
		public Domain(bool bCreateNew)
			: this()
		{
			if ( bCreateNew )
				this.CreateNew();
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="Domain"/> class.
		/// </summary>
		/// <param name="id">The id.</param>
		public Domain(int id)
			: this()
		{
			this.Load(id);
		}

		#endregion Initialization

		#region Public Members

		#region Properties

		/// <summary>
		/// Gets the allowed child types.
		/// </summary>
		/// <value>The allowed child types.</value>
		public override List<ItemType> AllowedChildTypes
		{
			get { return _LISTALLOWED; }
		}

		/// <summary>
		/// Gets the configuration paths.
		/// </summary>
		/// <value>The configuration paths.</value>
		public BindingListEx<ConfigurationPath> ConfigurationPaths
		{
			get
			{
				if ( _paths == null ) {
					_paths = Global.Data.GetConfigurationPaths(this.ID);
				}
				return _paths;
			}
		}

		/// <summary>
		/// Gets or sets the parent domain id.
		/// </summary>
		public override int DomainId
		{
			get
			{
				return getInt("parent_domain_id", -1);
			}
			set
			{
				setValue("DomainId", "parent_domain_id", value);
			}
		}

		/// <summary>
		/// Gets the extended properties.
		/// </summary>
		/// <value>The extended properties.</value>
		public DomainProperties ExtendedProperties
		{
			get
			{
				if ( _properties == null ) {
					_properties = getXmlSerializedObject<DomainProperties>("domain_properties");
					if ( _properties == null ) _properties = new DomainProperties();
				}
				return _properties;
			}
		}

		/// <summary>
		/// Gets the image.
		/// </summary>
		/// <value>The image.</value>
		public override Image Image
		{
			get { return Resources.domain; }
		}

		/// <summary>
		/// Gets the image key.
		/// </summary>
		/// <value>The image key.</value>
		public override string ImageKey
		{
			get { return "group"; }
		}

		/// <summary>
		/// Gets the type of the repository item.
		/// </summary>
		/// <value>The type of the repository item.</value>
		public override ItemType RepositoryItemType
		{
			get { return ItemType.Domain; }
		}

		/// <summary>
		/// Gets the repository item type description.
		/// </summary>
		/// <value>The repository item type description.</value>
		public override string RepositoryItemTypeDescription
		{
			get { return ""; }
		}

		/// <summary>
		/// Gets the name of the repository item type.
		/// </summary>
		/// <value>The name of the repository item type.</value>
		public override string RepositoryItemTypeName
		{
			get { return Resources.sDomain; }
		}

		/// <summary>
		/// Gets or sets the schema.
		/// </summary>
		/// <value>The schema.</value>
		public XmlSchema Schema
		{
			get
			{
				if ( _schema == null ) {
					_schema = getSchema("domain_schema");
				}
				return _schema;
			}
			set
			{
				_schema = value;
				setSchema("Schema", "domain_schema", _schema);
			}
		}

		/// <summary>
		/// Gets the selected image.
		/// </summary>
		/// <value>The selected image.</value>
		public override Image SelectedImage
		{
			get { return Resources.domain; }
		}

		/// <summary>
		/// Gets the selected image key.
		/// </summary>
		/// <value>The selected image key.</value>
		public override string SelectedImageKey
		{
			get { return "group"; }
		}

		/// <summary>
		/// Gets the name of the table.
		/// </summary>
		/// <value>The name of the table.</value>
		public override string TableName
		{
			get { return "domains"; }
		}

		/// <summary>
		/// Gets or sets the type.
		/// </summary>
		/// <value>The type.</value>
		public DomainType Type
		{
			get { return (DomainType)getValue("domain_type", DomainType.Domain); }
			set { setValue("Type", "domain_type", value); }
		}

		#endregion Properties

		#region Methods

		/// <summary>
		/// Copies this instance.
		/// </summary>
		/// <param name="deep"><c>true</c> to recursively copy the item and all subitems;
		/// <c>false</c> to copy only the item itself.</param>
		/// <returns>The copied item.</returns>
		public override IRepositoryItem Copy(bool deep)
		{
			Domain copy = new Domain(true);
			copy.InitializeServiceProvider(this);
			this.CopyDataRowToTarget(copy);
			return copy;
		}

		// new
		// override
		/// <summary>
		/// Gets the icon.
		/// </summary>
		/// <returns></returns>
		public override Icon GetIcon()
		{
			return Icon.FromHandle(Resources.domain.GetHicon());
		}

		/// <summary>
		/// Saves this instance.
		/// </summary>
		/// <returns></returns>
		public override bool Save()
		{
			if ( _properties != null ) {
				setXmlSerializedObject("ExtendedProperties", "domain_properties", _properties);
			}
			if ( _paths != null ) {
				Global.Data.SetConfigurationPaths(this.ID, _paths);
			}
			return base.Save();
		}

		#endregion Methods

		#endregion Public Members

		#region Internal Members

		#region Constant/Read-Only Fields

		internal const string ColumnDescription = "domain_desc";
		internal const string ColumnID = "domain_id";
		internal const string ColumnNText = "domain_ntext";
		internal const string ColumnName = "domain_nm";

		#endregion Constant/Read-Only Fields

		#endregion Internal Members

		#region Private Members

		#region Static Fields

		private static List<ItemType> _LISTALLOWED = new List<ItemType>(new ItemType[] {
					ItemType.Domain, ItemType.GenericFolder });

		#endregion Static Fields

		#region Fields

		private BindingListEx<ConfigurationPath> _paths = null;
		private DomainProperties _properties = null;
		private XmlSchema _schema = null;

		#endregion Fields

		#endregion Private Members

		#region Enumerations

		public enum DomainType
		{
			Domain = 0,
			Category
		}

		#endregion Enumerations

		#region Nested Types

		public class ConfigurationPath
		{
			#region Initialization

			/// <summary>
			/// Initializes a new instance of the <see cref="ConfigurationPath"/> class.
			/// </summary>
			public ConfigurationPath()
				: this(-1, "")
			{
			}

			/// <summary>
			/// Initializes a new instance of the <see cref="ConfigurationPath"/> class.
			/// </summary>
			/// <param name="path">The path.</param>
			public ConfigurationPath(string path)
				: this(-1, path)
			{
			}

			/// <summary>
			/// Initializes a new instance of the <see cref="ConfigurationPath"/> class.
			/// </summary>
			/// <param name="pathID">The path ID.</param>
			/// <param name="path">The path.</param>
			internal ConfigurationPath(int pathID, string path)
			{
				this.PathID = pathID;
				this.Path = path;
			}

			#endregion Initialization

			#region Public Members

			#region Properties

			/// <summary>
			/// Gets or sets the path.
			/// </summary>
			/// <value>The path.</value>
			public string Path
			{
				get;
				set;
			}

			/// <summary>
			/// Gets or sets the path ID.
			/// </summary>
			/// <value>The path ID.</value>
			public int PathID
			{
				get;
				protected set;
			}

			#endregion Properties

			#region Methods

			/// <summary>
			/// Returns a <see cref="System.String"/> that represents this instance.
			/// </summary>
			/// <returns>
			/// A <see cref="System.String"/> that represents this instance.
			/// </returns>
			public override string ToString()
			{
				return this.Path;
			}

			#endregion Methods

			#endregion Public Members
		}

		[Serializable]
		[XmlRoot(Namespace = "http://www.OpenComposite.com/Repository")]
		[XmlType(Namespace = "http://www.OpenComposite.com/Repository")]
		public class DomainProperties
		{
			#region Initialization

			/// <summary>
			/// Initializes a new instance of the <see cref="DomainProperties"/> class.
			/// </summary>
			public DomainProperties()
			{
				this.ConfigurableElements = new List<ConfigurableElement>();
				this.ConfigurationFileLocations = new List<string>();
			}

			#endregion Initialization

			#region Public Members

			#region Properties

			/// <summary>
			/// Gets or sets the configurable elements.
			/// </summary>
			/// <value>The configurable elements.</value>
			public List<ConfigurableElement> ConfigurableElements
			{
				get;
				set;
			}

			/// <summary>
			/// Gets or sets the configuration file locations.
			/// </summary>
			/// <value>The configuration file locations.</value>
			public List<string> ConfigurationFileLocations
			{
				get;
				set;
			}

			#endregion Properties

			#region Methods

			/// <summary>
			/// Gets the configurable elements string.
			/// </summary>
			/// <returns></returns>
			public string GetConfigurableElementsString()
			{
				return string.Join(
					", ",
					this.ConfigurableElements.ConvertAll<string>(
						delegate(ConfigurableElement element)
						{
							return OpenComposite.EII.Forms.ConfigurableElements.GetString(element);
						}).ToArray());
			}

			#endregion Methods

			#endregion Public Members
		}

		#endregion Nested Types
	}
}